package org.formal.system.shiro.manager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.formal.system.entity.ResourceEntity;
import org.formal.system.entity.UserEntity;
import org.formal.system.service.ResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.util.StringUtil;
/**
 * 
 * @author jiangyan
 *
 */
@Service
public class ShiroService {

	@Resource
	private  ShiroFilterFactoryBean shiroFilterFactoryBean;

	@Resource
	private ResourceService resourceService;

	@Autowired
	private MemorySessionDAO memorySessionDAO;

	public Map<String,String> loadFilterChainDefinitions(){
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/formal/**","anon");
		filterChainDefinitionMap.put("/**", "authc");
		List<ResourceEntity> resources = this.resourceService.loadUserResources();
		for(ResourceEntity resource:resources){
			if (StringUtil.isNotEmpty(resource.getUrl())) {
				String permission = "perms[" + resource.getUrl()+ "]";
				filterChainDefinitionMap.put(resource.getUrl(),permission);
			}
		}
		Session session = TokenManager.getSession();
		session.setAttribute("resources", resources);
		return filterChainDefinitionMap;
	}

	public void updatePermission() {

		synchronized (shiroFilterFactoryBean) {

			AbstractShiroFilter shiroFilter = null;
			try {
				shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean
						.getObject();
			} catch (Exception e) {
				throw new RuntimeException(
						"get ShiroFilter from shiroFilterFactoryBean error!");
			}

			PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
					.getFilterChainResolver();
			DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
					.getFilterChainManager();

			// 清空老的权限控制
			manager.getFilterChains().clear();

			shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
			shiroFilterFactoryBean
			.setFilterChainDefinitionMap(loadFilterChainDefinitions());
			// 重新构建生成
			Map<String, String> chains = shiroFilterFactoryBean
					.getFilterChainDefinitionMap();
			for (Map.Entry<String, String> entry : chains.entrySet()) {
				String url = entry.getKey();
				String chainDefinition = entry.getValue().trim()
						.replace(" ", "");
				manager.createChain(url, chainDefinition);
			}
		}
	}

	/**
	 * 根据userId 清除当前session存在的用户的权限缓存
	 * @param userIds 已经修改了权限的userId
	 */
	public void clearUserAuthByUserId(List<String> userIds){
		if(null == userIds || userIds.size() == 0) { return ;}
		//获取所有session
		Collection<Session> sessions = memorySessionDAO.getActiveSessions();
		//定义返回
		List<SimplePrincipalCollection> list = new ArrayList<SimplePrincipalCollection>();
		for (Session session:sessions){
			//获取session登录信息。
			Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if(null != obj && obj instanceof SimplePrincipalCollection){
				//强转
				SimplePrincipalCollection spc = (SimplePrincipalCollection)obj;
				//判断用户，匹配用户ID。
				obj = spc.getPrimaryPrincipal();
				if(null != obj && obj instanceof UserEntity){
					UserEntity user = (UserEntity) obj;
					System.out.println("user:"+user);
					//比较用户ID，符合即加入集合
					if(null != user && userIds.indexOf(user.getId())>-1 ){
						list.add(spc);
					}
				}
			}
		}
		RealmSecurityManager securityManager =
				(RealmSecurityManager) SecurityUtils.getSecurityManager();
		SimpleRealm realm = (SimpleRealm)securityManager.getRealms().iterator().next();
		for (SimplePrincipalCollection principals : list) {
			 realm.clearCachedAuthorization(principals);
		}
	}
}
